package com.zbkj.crmeb.pdd.service.impl;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Objects;

import javax.annotation.Resource;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.common.CommonPage;
import com.common.PageParamRequest;
import com.constants.Constants;
import com.constants.WeChatConstants;
import com.crmeb.core.config.MybatisPlusConfig;
import com.crmeb.core.exception.CrmebException;
import com.crmeb.core.utils.TableNameUtil;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.pdd.pop.sdk.common.util.JsonUtil;
import com.pdd.pop.sdk.http.PopAccessTokenClient;
import com.pdd.pop.sdk.http.PopClient;
import com.pdd.pop.sdk.http.PopHttpClient;
import com.pdd.pop.sdk.http.api.pop.request.PddGoodsAddRequest;
import com.pdd.pop.sdk.http.api.pop.request.PddGoodsAddRequest.GoodsPropertiesItem;
import com.pdd.pop.sdk.http.api.pop.request.PddGoodsAddRequest.SkuListItem;
import com.pdd.pop.sdk.http.api.pop.request.PddGoodsAuthorizationCatsRequest;
import com.pdd.pop.sdk.http.api.pop.request.PddGoodsCatRuleGetRequest;
import com.pdd.pop.sdk.http.api.pop.request.PddGoodsCountryGetRequest;
import com.pdd.pop.sdk.http.api.pop.request.PddGoodsImageUploadRequest;
import com.pdd.pop.sdk.http.api.pop.request.PddGoodsLogisticsTemplateGetRequest;
import com.pdd.pop.sdk.http.api.pop.request.PddGoodsQuantityUpdateRequest;
import com.pdd.pop.sdk.http.api.pop.request.PddGoodsSpecGetRequest;
import com.pdd.pop.sdk.http.api.pop.request.PddGoodsSpecIdGetRequest;
import com.pdd.pop.sdk.http.api.pop.request.PddMallInfoGetRequest;
import com.pdd.pop.sdk.http.api.pop.response.PddGoodsAddResponse;
import com.pdd.pop.sdk.http.api.pop.response.PddGoodsAuthorizationCatsResponse;
import com.pdd.pop.sdk.http.api.pop.response.PddGoodsCatRuleGetResponse;
import com.pdd.pop.sdk.http.api.pop.response.PddGoodsCountryGetResponse;
import com.pdd.pop.sdk.http.api.pop.response.PddGoodsImageUploadResponse;
import com.pdd.pop.sdk.http.api.pop.response.PddGoodsLogisticsTemplateGetResponse;
import com.pdd.pop.sdk.http.api.pop.response.PddGoodsQuantityUpdateResponse;
import com.pdd.pop.sdk.http.api.pop.response.PddGoodsSpecGetResponse;
import com.pdd.pop.sdk.http.api.pop.response.PddGoodsSpecIdGetResponse;
import com.pdd.pop.sdk.http.api.pop.response.PddMallInfoGetResponse;
import com.pdd.pop.sdk.http.token.AccessTokenResponse;
import com.utils.UploadUtil;
import com.zbkj.crmeb.pdd.dao.PddAccountDao;
import com.zbkj.crmeb.pdd.model.PddAccount;
import com.zbkj.crmeb.pdd.request.PddAccountRequest;
import com.zbkj.crmeb.pdd.request.SyPddGoodsAddRequest;
import com.zbkj.crmeb.pdd.request.SyPddGoodsPropertyRequest;
import com.zbkj.crmeb.pdd.request.SyPddSkuListItemRequest;
import com.zbkj.crmeb.pdd.response.PddAccountResponse;
import com.zbkj.crmeb.pdd.service.PddAccountService;
import com.zbkj.crmeb.store.model.StoreProductAttrValue;
import com.zbkj.crmeb.store.model.StoreProductMer;
import com.zbkj.crmeb.store.response.StoreProductAttrValueResponse;
import com.zbkj.crmeb.store.response.StoreProductResponse;
import com.zbkj.crmeb.store.service.StoreProductAttrValueService;
import com.zbkj.crmeb.store.service.StoreProductDescriptionService;
import com.zbkj.crmeb.store.service.StoreProductMerService;
import com.zbkj.crmeb.store.service.StoreProductService;
import com.zbkj.crmeb.system.model.SystemConfig;
import com.zbkj.crmeb.system.service.SystemConfigService;

import lombok.extern.slf4j.Slf4j;

/**
 * 
 * @author daigb
 * @date:  2022-11-14 14:31
 */
@Slf4j
@Service
public class PddAccountServiceImpl extends ServiceImpl<PddAccountDao, PddAccount> implements PddAccountService {
    @Resource
    private PddAccountDao pddAccountDao;
    @Resource
    private StoreProductService storeProductService;
    @Resource
    private StoreProductAttrValueService storeProductAttrValueService;
    @Resource
    private StoreProductDescriptionService storeProductDescriptionService;
    @Resource
    private SystemConfigService systemConfigService;
    @Resource
    private StoreProductMerService storeProductMerService;

    @Value("${pdd.auth.url}")
    private String url;
    @Value("${pdd.auth.clientId}")
    private String clientId;
    @Value("${pdd.auth.clientSecret}")
    private String clientSecret;
    
	PopClient client;
	private PopClient getClient() {
		if(null == client) {
			synchronized (PddAccountServiceImpl.class) {
				if(null == client){
					client = new PopHttpClient(clientId, clientSecret);
				}
			}
		}
		
		return client;
	}

    /**
     * 分页查询
     */
    @Override
    public PageInfo<PddAccountResponse> pageEntity(PageParamRequest pageParamRequest, Integer merId) {
        Page<Object> page = PageHelper.startPage(pageParamRequest.getPage(), pageParamRequest.getLimit());
        List<PddAccount> pddAccounts = pddAccountDao.selectList(Wrappers.<PddAccount>lambdaQuery()
        		.eq(PddAccount :: getMerId, merId)
                .orderByDesc(PddAccount::getCreateTime)
        		);

        // 对象复制
        List<PddAccountResponse> responses = new ArrayList<>();
        for(PddAccount pddAccount : pddAccounts) {
        	PddAccountResponse response = new PddAccountResponse();
            BeanUtils.copyProperties(pddAccount, response);
            // 生成授权链接
            String backUrl = "";
			try {
				// 回调地址
				String doMain = systemConfigService.getValueByKeyException(WeChatConstants.DOMAIN_URL);
				backUrl = URLEncoder.encode(doMain + WeChatConstants.PDD_AUTH_BACK_URL, "UTF-8");
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
    		String authUrl = url + "?response_type=code&client_id=" + clientId + "&redirect_uri=" + backUrl + "&state=" + pddAccount.getId();
    		response.setUrl(authUrl);
    		// 判断授权是否失效
    		if(StringUtils.isBlank(pddAccount.getToken())) {
    			response.setStatus(0);
    		} else if(null == pddAccount.getExpireTime() || (StringUtils.isNotBlank(pddAccount.getToken()) && -1 == pddAccount.getExpireTime().compareTo(new Date()))) {
    			response.setStatus(2);
    		} else {
    			response.setStatus(1);
    		}
            
            responses.add(response);
        }

        return CommonPage.copyPageInfo(page, responses);
    }

    /**
     * 更新账户数据
     */
	@Override
	public Boolean saveOrUpdateEntity(PddAccountRequest pddAccountRequest, Integer merId) {
		PddAccount pddAccount = new PddAccount();
        BeanUtils.copyProperties(pddAccountRequest, pddAccount);
        pddAccount.setMerId(merId);
		
        return this.saveOrUpdate(pddAccount);
	}

	/**
	 * 删除
	 */
	@Override
	public Boolean delEntity(Integer id, Integer merId) {
		return this.removeById(id);
	}

	/**
	 * 拼多多账号授权回调处理
	 */
	@Override
	public Boolean notifyAccount(String state, String code) {
		// 获取token
		PddAccount pddAccount = this.getById(state);
		if(Objects.isNull(pddAccount)) {
			log.info("--------------- 拼多多授权回调商户不存在 ---------------");
	        return false;
		}
		
		try {
			PopClient client = new PopHttpClient(clientId, clientSecret);
			PopAccessTokenClient popAccessTokenClient = new PopAccessTokenClient(clientId, clientSecret);
			AccessTokenResponse accessTokenResponse = popAccessTokenClient.generate(code);
			// 返回token
			String token = accessTokenResponse.getAccessToken();
			// 有效期(秒)
			Integer expiresIn = accessTokenResponse.getExpiresIn();
			// 通过授权token获取账号
			PddMallInfoGetRequest pddMallInfoGetRequest = new PddMallInfoGetRequest();
			PddMallInfoGetResponse response = client.syncInvoke(pddMallInfoGetRequest, token);
			log.info("--------------- 拼多多api获取商户信息返回结果: {} ---------------", JSON.toJSONString(response));
			String account = response.getMallInfoGetResponse().getMallId() + "";
			String name = response.getMallInfoGetResponse().getMallName() + "";
			if(StringUtils.isBlank(account)) {
				log.info("--------------- 拼多多通过code获取商户信息失败: code={} ---------------", code);
			    return false;
			}
			// 有效期
			Date date = new Date();
			Calendar calendar = new GregorianCalendar();
			calendar.setTime(date);
			calendar.add(Calendar.SECOND, expiresIn);
			date = calendar.getTime();
			// 更新token信息
			this.update(Wrappers.<PddAccount>lambdaUpdate()
					.set(PddAccount :: getToken, token)
					.set(PddAccount :: getExpireTime, date)
					.set(PddAccount :: getName, name)
					.eq(PddAccount :: getAccount, account)
					);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return true;
	}
	
	/**
	 * 获取商户账号token(未考虑存在多个店铺情况)
	 * @author daigb
	 * @date:  2022-11-28 15:40
	 */
	private String getToken(Integer merId) {
		PddAccount pddAccount = this.getOne(Wrappers.<PddAccount>lambdaQuery()
				.eq(PddAccount :: getMerId, merId)
				.last("Limit 1")
				);
		
		return Objects.isNull(pddAccount) ? "" : pddAccount.getToken();
	}

	/**
	 * 获取店铺可发布类目信息
	 * @throws Exception 
	 */
	@Override
	public PddGoodsAuthorizationCatsResponse goodsAuthorizationCats(Integer merId, Long cateId) throws Exception {
		PddGoodsAuthorizationCatsRequest request = new PddGoodsAuthorizationCatsRequest();
		request.setParentCatId(cateId);
	    PddGoodsAuthorizationCatsResponse response = getClient().syncInvoke(request, getToken(merId));
	    
	    return response;
	}
	
	/**
	 * 获取类目发布规则
	 * @throws Exception 
	 */
	@Override
	public PddGoodsCatRuleGetResponse goodsCatRule(Integer merId, Long cateId) throws Exception {
		PddGoodsCatRuleGetRequest request = new PddGoodsCatRuleGetRequest();
		request.setCatId(cateId);
		PddGoodsCatRuleGetResponse response = getClient().syncInvoke(request, getToken(merId));
		
		return response;
	}
	
	/**
	 * 商品国家获取
	 * @throws Exception 
	 */
	@Override
	public PddGoodsCountryGetResponse goodsCountry(Integer merId) throws Exception {
		PddGoodsCountryGetRequest request = new PddGoodsCountryGetRequest();
		PddGoodsCountryGetResponse response = getClient().syncInvoke(request, getToken(merId));
		
		return response;
	}
	
	/**
	 * 运费模板获取
	 * @throws Exception 
	 */
	@Override
	public PddGoodsLogisticsTemplateGetResponse goodsLogisticsTemplate(Integer merId) throws Exception {
		PddGoodsLogisticsTemplateGetRequest request = new PddGoodsLogisticsTemplateGetRequest();
	    PddGoodsLogisticsTemplateGetResponse response = getClient().syncInvoke(request, getToken(merId));
		
		return response;
	}

	/**
	 * 类目规则获取
	 */
	@Override
	public PddGoodsSpecGetResponse goodsSpec(Long cateId, Integer merId) throws Exception {
		PddGoodsSpecGetRequest request = new PddGoodsSpecGetRequest();
		request.setCatId(cateId);
	    PddGoodsSpecGetResponse response = getClient().syncInvoke(request, getToken(merId));
	    
		return response;
	}

	/**
	 * 新增商家规格
	 */
	@Override
	public PddGoodsSpecIdGetResponse goodsSpecId(Long specId, String specName, Integer merId) throws Exception {
		PddGoodsSpecIdGetRequest request = new PddGoodsSpecIdGetRequest();
		request.setParentSpecId(specId);
		request.setSpecName(specName);
	    PddGoodsSpecIdGetResponse response = getClient().syncInvoke(request, getToken(merId));
	    
		return response;
	}

	/**
	 * 商品推送至拼多多
	 */
	@Override
	public Boolean goodsPush(SyPddGoodsAddRequest syPddGoodsAddRequest, Integer merId) throws Exception {
		Integer productId = syPddGoodsAddRequest.getId();
		StoreProductResponse product = storeProductService.getByProductId(productId);
		String token = getToken(merId);
		// 构建拼多多商品数据
		PddGoodsAddRequest request = buildPddProduct(product, syPddGoodsAddRequest, token);
		PddGoodsAddResponse response = getClient().syncInvoke(request, token);
		log.info("--------------- 拼多多上传商品返回结果: {}", JsonUtil.transferToJson(response));
		if(null != response.getErrorResponse()) {
			throw new CrmebException(response.getErrorResponse().getErrorMsg());
		}
		// 绑定拼多多商品id
		Long pddGoodsId = response.getGoodsAddResponse().getGoodsId(); 
		StoreProductMer merProduct = storeProductMerService.getOne(Wrappers.<StoreProductMer>lambdaQuery()
				.eq(StoreProductMer :: getProductId, productId)
				);
		StoreProductMer storeProductMer = new StoreProductMer();
		if(null != merProduct) {
			storeProductMer.setId(merProduct.getId());
		}
		storeProductMer.setProductId(productId);
		storeProductMer.setPddGoodsId(pddGoodsId.toString());
		storeProductMerService.saveOrUpdate(storeProductMer);
		
		return true;
	}
	
	/**
	 * 构建拼多多待推送商品
	 * @author daigb
	 * @date:  2022-11-28 16:20
	 */
	private PddGoodsAddRequest buildPddProduct(StoreProductResponse product, SyPddGoodsAddRequest syPddGoodsAddRequest, String token) {
		PddGoodsAddRequest pddGoodsAddRequest = new PddGoodsAddRequest();
		// 商品轮播图, 图片尺寸长宽比1：1且尺寸不低于480px
		List<String> galleryImgs = new ArrayList<>();
		JSONArray sliderImage = JSONArray.parseArray(product.getSliderImage());
		for(int i=0; i<sliderImage.size(); i++) {
			String pddImg = uploadImg(sliderImage.getString(i), token);
			if(null != pddImg) {
				galleryImgs.add(pddImg);
			}
		}
		pddGoodsAddRequest.setCarouselGallery(galleryImgs); // 商品轮播图
		pddGoodsAddRequest.setCatId(syPddGoodsAddRequest.getCatId()); // 类目id
		pddGoodsAddRequest.setCostTemplateId(syPddGoodsAddRequest.getCostTemplateId()); // 运费模板
		pddGoodsAddRequest.setCountryId(syPddGoodsAddRequest.getCountryId()); // 国家id
		pddGoodsAddRequest.setDetailGallery(galleryImgs); // 详情图
		String description = StringUtils.isBlank(product.getStoreInfo()) ? "默认描述" : product.getStoreInfo();
		if(500 < description.length()) {
			description = description.substring(0, 500);
		}
		pddGoodsAddRequest.setGoodsDesc(description); // 商品描述
		pddGoodsAddRequest.setGoodsName(syPddGoodsAddRequest.getStoreName()); // 商品标题
		pddGoodsAddRequest.setGoodsType(syPddGoodsAddRequest.getGoodsType()); // 商品类型, 根据类目规则制定
		pddGoodsAddRequest.setIsFolt(true); // 支持假一赔十
		pddGoodsAddRequest.setIsPreSale(syPddGoodsAddRequest.getIsPreSale()); // 是否预售
		pddGoodsAddRequest.setPreSaleTime(syPddGoodsAddRequest.getPreSaleTime()); // 预售时间
		pddGoodsAddRequest.setIsRefundable(true); // 7天无理由退换货
		pddGoodsAddRequest.setMarketPrice(syPddGoodsAddRequest.getMarketPrice()); // 参考价格，单位为分
		pddGoodsAddRequest.setOutGoodsId(product.getBarCode()); // 商品goods外部编码
		pddGoodsAddRequest.setOutSourceGoodsId(product.getId().toString()); // 第三方商品Id
		pddGoodsAddRequest.setSecondHand(false); // 是否二手商品
		pddGoodsAddRequest.setShipmentLimitSecond(syPddGoodsAddRequest.getShipmentLimitSecond()); // 承诺发货时间（秒）
		pddGoodsAddRequest.setWarehouse(syPddGoodsAddRequest.getWarehouse()); // 保税仓，只在goods_type=3（直供商品）时入参, 需根据类目规则来
		pddGoodsAddRequest.setTwoPiecesDiscount(syPddGoodsAddRequest.getTwoPiecesDiscount()); // 满两件打折比例

		// 拼多多商品属性
		List<GoodsPropertiesItem> goodsProperties = new ArrayList<>();
		List<SyPddGoodsPropertyRequest> goodsPropertys = syPddGoodsAddRequest.getGoodsPropertys();
		for(SyPddGoodsPropertyRequest property : goodsPropertys) {
			GoodsPropertiesItem goodsPropertiesItem = new GoodsPropertiesItem();
			goodsPropertiesItem.setRefPid(property.getRefPid());
			goodsPropertiesItem.setVid(property.getVid());
			goodsPropertiesItem.setValue(property.getValue());
			goodsProperties.add(goodsPropertiesItem);
		}
		pddGoodsAddRequest.setGoodsProperties(goodsProperties);
		
		// 新增sku属性
		List<SkuListItem> skuList = new ArrayList<>();
		// 商品sku信息
		String skuImg = "";
		String skuPddImg = "";
		List<SyPddSkuListItemRequest> pddSkuListItemRequests = syPddGoodsAddRequest.getItems();
		for(StoreProductAttrValueResponse value : product.getAttrValue()) {
			// 转化后拼多多sku属性
			SyPddSkuListItemRequest pddSkuItem = new SyPddSkuListItemRequest();
			for(SyPddSkuListItemRequest item : pddSkuListItemRequests) {
				if(value.getSourceSkuId().equals(item.getOutSourceSkuId())) {
					pddSkuItem = item;
				}
			}
			
			SkuListItem skuListItem = new SkuListItem();
			skuListItem.setIsOnsale(1); // 上架
			skuListItem.setLimitQuantity(999L); // 只入参999
			skuListItem.setMultiPrice(pddSkuItem.getMultiPrice()); // 团购价, 目前打九折
			skuListItem.setOutSkuSn(value.getSourceSkuId()); // 第三方skuid
			skuListItem.setOutSourceSkuId(value.getSourceSkuId()); // 第三方skuid
			skuListItem.setPrice(pddSkuItem.getPrice()); // 单买属性
			skuListItem.setQuantity(value.getStock().longValue());
			// sku属性(需要新增商家规格)
//			List<PddGoodsAddRequest.SkuListItemSkuPropertiesItem> skuPropers = new ArrayList<>();
//			PddGoodsAddRequest.SkuListItemSkuPropertiesItem skuItem = new PddGoodsAddRequest.SkuListItemSkuPropertiesItem();
//			skuItem.setPunit(pddSkuItem.getPunit());
//			skuItem.setRefPid(pddSkuItem.getRefPid());
//			skuItem.setValue(pddSkuItem.getValue());
//			skuItem.setVid(pddSkuItem.getVid());
//			skuPropers.add(skuItem);
//			skuListItem.setSkuProperties(skuPropers);
			skuListItem.setSpecIdList(pddSkuItem.getSpecIdList());
			if(!skuImg.equals(value.getImage())) {
				skuPddImg = uploadImg(value.getImage(), token);
			}
			skuListItem.setThumbUrl(skuPddImg); // sku图片
			skuListItem.setWeight(500L);
			
			skuList.add(skuListItem);
			skuImg = value.getImage();
		}
		pddGoodsAddRequest.setSkuList(skuList);
		
		return pddGoodsAddRequest;
	}
	
	/**
	 * 上传图片到拼多多图片空间
	 * @author daigb
	 * @date:  2022-11-29 13:59
	 */
	private String uploadImg(String imgUrl, String token) {
		try {
			PddGoodsImageUploadRequest request = new PddGoodsImageUploadRequest();
			String base64Img = UploadUtil.getImgUrlToBase64ToSize(imgUrl, 1500, 1200);
			request.setImage("data:image/jpg;base64," + base64Img);
			PddGoodsImageUploadResponse response = getClient().syncInvoke(request, token);
			
			return response.getGoodsImageUploadResponse().getImageUrl();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return null;
	}

	@Override
	public void goodsStockJobUpdate() throws Exception {
		log.info("--------------- 执行拼多多上架商品库存更新任务 ---------------");
		// 查询所有开放了拼多多推送的商家列表
		PddGoodsQuantityUpdateRequest request = new PddGoodsQuantityUpdateRequest();
		List<SystemConfig> systemConfigs = systemConfigService.list(Wrappers.<SystemConfig>lambdaQuery()
				.likeRight(SystemConfig :: getName, Constants.CONFIG_PUSH_PDD_MER)
				.eq(SystemConfig :: getValue, 1)
				);
		// 查询商户表已推送拼多多商品数据
		int count = 0;
		for(SystemConfig systemConfig : systemConfigs) {
			String merIdStr = systemConfig.getName().split("_")[3];
			String token = getToken(Integer.parseInt(merIdStr));
			
			// 查询商户商品表
            MybatisPlusConfig.tableNameMp.set(TableNameUtil.getProductMerName(merIdStr));
            List<StoreProductMer> storeProductMers = storeProductMerService.list(Wrappers.<StoreProductMer>lambdaQuery()
            		.isNotNull(StoreProductMer :: getPddGoodsId)
            		);
            // 查询商品对应的sku并更新拼多多库存(目前不保证新增的规格和删除的规格问题)
            for(StoreProductMer storeProductMer : storeProductMers) {
            	List<StoreProductAttrValue> values = storeProductAttrValueService.getListByProductId(storeProductMer.getProductId());
            	try {
					for(StoreProductAttrValue value : values) {
						request.setGoodsId(Long.valueOf(storeProductMer.getPddGoodsId()));
						request.setQuantity(Long.valueOf(value.getStock()));
						request.setOuterId(value.getSourceSkuId());
					    getClient().syncInvoke(request, token);
					    count++;
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
            }
		}
		
		log.info("--------------- 执行拼多多上架商品库存更新任务完成, 总数:{} ---------------", count);
	}

}

